#include "CAN.h"				// CAN driver
/*****************************************************************************
 *
 * Microchip DeviceNet Stack (Connection Object Source)
 *
 *****************************************************************************
 * FileName:        conn.c
 * Dependencies:    
 * Processor:       PIC18F with CAN
 * Compiler:       	C18 02.20.00 or higher
 * Linker:          MPLINK 03.40.00 or higher
 * Company:         Microchip Technology Incorporated
 *
 * Software License Agreement
 *
 * The software supplied herewith by Microchip Technology Incorporated
 * (the "Company") is intended and supplied to you, the Company's
 * customer, for use solely and exclusively with products manufactured
 * by the Company. 
 *
 * The software is owned by the Company and/or its supplier, and is 
 * protected under applicable copyright laws. All rights are reserved. 
 * Any use in violation of the foregoing restrictions may subject the 
 * user to criminal sanctions under applicable laws, as well as to 
 * civil liability for the breach of the terms and conditions of this 
 * license.
 *
 * THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTIES, 
 * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED 
 * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 
 * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT, 
 * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR 
 * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
 *
 *
 * This file contains the Connection Object managing functions. Based on a 
 * variety of conditions, events are generated for specific instances. Refer
 * to section 5-4 of Volume 1 of the DeviceNet specification.
 * 
 *
 *
 * Author               Date        Comment
 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 * Ross Fosler			04/28/03	...	
 * 
 *****************************************************************************/




#include	"dnetdef.h"			// Global definitions file
#include 	"typedefs.h"

#include	"conn.h"			// Internal definitions

#include	"services.h"		// Service codes
#include	"errors.h"			// Error codes
#include	"class.h"			// Class codes

#include	"route.h"			// Global symbols defined by the Router Obj
#include	"dnet.h"			// Global symbols defined by the DeviceNet Obj




#define	_CONN_REVISION		0x01
#define	_ATTRIB_REVISION	1


/*********************************************************************
 * Flag registers for read and write control
 ********************************************************************/		
 FLAGS _rxFlag;			// Receive control and indication
 FLAGS _txFlag;			// Transmit control and indication
 FLAGS _txFinFlags;		// Transmit finish control and indication
 FLAGS _existentFlags;	// Indicates the existance
 FLAGS _establishFlags;	// Indicates established connections
 unsigned char _deSer;	// Control register to de-serialize transmissions

/*********************************************************************
 * Function:        void _ConnInit(void)
 *
 * PreCondition:    The CAN (or other I/O) driver must be initialized
 *					prior to calling this function.
 *
 * Input:       	none		
 *                  
 * Output:      	none	
 *
 * Side Effects:    none
 *
 * Overview:        Initialize the connection object.
 *
 * Note:            During this process the Unconnected Explicit 
 *					Messaging and Duplicate ID Messaging connections
 *					are created.
 ********************************************************************/
void _ConnInit(void)
{
	// Initialize all global connection related variables
	_txFlag.byte = 0;
	_rxFlag.byte = 0;
	_txFinFlags.byte = 0;
	_existentFlags.byte = 0;
	_establishFlags.byte = 0;
	_deSer = 0;

	// Automatically create the duplicate ID and 
	// unconnected explicit messaging connections
	_Conn6Create();
	_Conn7Create();

	// Initialize all connections to there non-existent state
	uConn1.attrib.state = _STATE_NON_EXISTENT;

	#if SUPPORT_POLLED || SUPPORT_COS_BOTH_DIR
	uConn2.attrib.state = _STATE_NON_EXISTENT;
	#endif

	#if SUPPORT_BIT_STROBED
	uConn3.attrib.state = _STATE_NON_EXISTENT;
	#endif

	#if SUPPORT_COS || SUPPORT_CYCLIC 
	uConn4.attrib.state = _STATE_NON_EXISTENT;
	#endif

	#if SUPPORT_MULTICAST_POLL
	uConn5.attrib.state = _STATE_NON_EXISTENT;
	#endif
}


/*********************************************************************
 * Function:        unsigned char _ConnCreate(enum T_CONTYPE connType)
 *
 * PreCondition:    
 *
 * Input:       		
 *                  
 * Output:      	
 *
 * Side Effects:    
 *
 * Overview:        Returns a handle to the connection 
 *
 * Note:            Although a handle is returned, it is not required
 *					to be stored since this is a static model, where
 *					the instance numbers are fixed.
 ********************************************************************/
//unsigned char _ConnCreate(CONTYPE connType)
//{
//	switch (connType)
//	{
//		case CONTYPE_EXPLICIT: 		return(_Conn1Create()); // Explicit messaging connection
//		
//		#if SUPPORT_POLLED || SUPPORT_COS_BOTH_DIR
//		case CONTYPE_POLL: 			return(_Conn2Create());	// Poll I/O connection
//		#endif
//
//		#if SUPPORT_BIT_STROBED
//		case CONTYPE_BIT_STROBE: 	return(_Conn3Create());	// Bit-Strobe I/O connection
//		#endif
//
//		#if SUPPORT_COS || SUPPORT_CYCLIC
//		case CONTYPE_COS_CYCLIC: 	return(_Conn4Create());	// COS/Cyclic I/O connection
//		#endif
//
//		#if SUPPORT_MULTICAST_POLL
//		case CONTYPE_MULTICAST: 	return(_Conn5Create());	// Multicast Poll connection
//		#endif
//
//		case CONTYPE_UNC_EXPLICIT: 	return(_Conn6Create());	// Unconnected Explicit messaging connection
//		case CONTYPE_DUPLICATE_ID: 	return(_Conn7Create());	// Duplicate ID check message
//		default: return (0);
//	}
//}




/*********************************************************************
 * Function:        void _ConnClose(void)
 *
 * PreCondition:    
 *
 * Input:       		
 *                  
 * Output:      	
 *
 * Side Effects:    
 *
 * Overview:        Closes the specified connection 
 *
 * Note:            None
 ********************************************************************/
//void _ConnClose(unsigned char hInstance)
//{
//	switch (hInstance)
//	{
//		case 1:	_Conn1Close(); break;
//		
//		#if SUPPORT_POLLED || SUPPORT_COS_BOTH_DIR
//		case 2:	_Conn2Close(); break;
//		#endif
//
//		#if SUPPORT_BIT_STROBED
//		case 3:	_Conn3Close(); break;
//		#endif
//
//		#if SUPPORT_COS || SUPPORT_CYCLIC
//		case 4: _Conn4Close(); break;
//		#endif
//
//		#if SUPPORT_MULTICAST_POLL
//		case 5: _Conn5Close(); break;
//		#endif
//
//		case 6:	_Conn6Close(); break;
//		case 7:	_Conn7Close(); break;
//	}
//}


/*********************************************************************
 * Function:        unsigned char _ConnReadRdy(unsigned char hInstance)
 *
 * PreCondition:    
 *
 * Input:       	unsigned char handle to the instance
 *                  
 * Output:      	unsigned char 
 *
 * Side Effects:    none
 *
 * Overview:        Returns true if there is data in the read buffer 
 *					and the connection is established.
 *
 * Note:            None
 ********************************************************************/
unsigned char _ConnReadRdy(unsigned char hInstance)
{
	switch (hInstance)
	{
		case 1:	return (_rxFlag.bits.expl && _establishFlags.bits.expl);
		
		#if SUPPORT_POLLED || SUPPORT_COS_BOTH_DIR
		case 2:	return (_rxFlag.bits.poll && _establishFlags.bits.poll);
		#endif

		#if SUPPORT_BIT_STROBED
		case 3:	return (_rxFlag.bits.strobe && _establishFlags.bits.strobe);
		#endif

		#if SUPPORT_COS || SUPPORT_CYCLIC
		case 4: return (_rxFlag.bits.cos && _establishFlags.bits.cos);
		#endif

		#if SUPPORT_MULTICAST_POLL
		case 5: return (_rxFlag.bits.multi && _establishFlags.bits.multi);
		#endif

		case 6:	return (_rxFlag.bits.uexpl);
		case 7:	return (_rxFlag.bits.dupid);
		default: return (0);
	}
}



/*********************************************************************
 * Function:        unsigned char _ConnWriteRdy(unsigned char hInstance)
 *
 * PreCondition:    
 *
 * Input:       	unsigned char handle to instance
 *                  
 * Output:      	unsigned char
 *
 * Side Effects:    
 *
 * Overview:        Returns true if the buffer is available. 
 *
 * Note:            The application must call this function prior to 
 *					loading the buffer. Otherwise any message already
 *					queued to send will be corrupted.
 ********************************************************************/
unsigned char _ConnWriteRdy(unsigned char hInstance)	
{
	switch (hInstance)
	{
		case 1:	return (!_txFlag.bits.expl && _establishFlags.bits.expl);
	
		#if SUPPORT_POLLED || SUPPORT_COS_BOTH_DIR
		case 2:	return (!_txFlag.bits.poll && _establishFlags.bits.poll);
		#endif

		#if SUPPORT_BIT_STROBED
		case 3:	return (!_txFlag.bits.strobe && _establishFlags.bits.strobe);
		#endif

		#if SUPPORT_COS || SUPPORT_CYCLIC
		case 4: return (!_txFlag.bits.cos && _establishFlags.bits.cos);
		#endif

		#if SUPPORT_MULTICAST_POLL
		case 5: return (!_txFlag.bits.multi && _establishFlags.bits.multi);
		#endif

		case 6:	return (!_txFlag.bits.uexpl);
		case 7:	return (!_txFlag.bits.dupid);
		default: return (0);
	}	
}


/*********************************************************************
 * Function:        unsigned char _ConnWriteFin(unsigned char hInstance)
 *
 * PreCondition:    
 *
 * Input:       	unsigned char handle to instance	
 *                  
 * Output:      	unsigned char
 *
 * Side Effects:    
 *
 * Overview:        Returns true if the buffer has placed data on the bus. 
 *
 * Note:            None
 ********************************************************************/
unsigned char _ConnWriteFin(unsigned char hInstance)	
{
	unsigned char temp;
	
	switch (hInstance)
	{
		case 1:	
			temp = _txFinFlags.bits.expl;
			_txFinFlags.bits.expl = 0;
			return (temp);

		#if SUPPORT_POLLED || SUPPORT_COS_BOTH_DIR
		case 2:	
			temp = _txFinFlags.bits.poll;
			_txFinFlags.bits.poll = 0;
			return (temp);
		#endif

		#if SUPPORT_BIT_STROBED
		case 3:	
			temp = _txFinFlags.bits.strobe;
			_txFinFlags.bits.strobe = 0;
			return (temp);
		#endif

		#if SUPPORT_COS || SUPPORT_CYCLIC
		case 4: 
			temp = _txFinFlags.bits.cos;
			_txFinFlags.bits.cos = 0;
			return (temp);
		#endif

		#if SUPPORT_MULTICAST_POLL
		case 5: 
			temp = _txFinFlags.bits.multi;
			_txFinFlags.bits.multi = 0;
			return (temp);
		#endif

		case 6:	
			temp = _txFinFlags.bits.uexpl;
			_txFinFlags.bits.uexpl = 0;
			return (temp);
			
		case 7:	
			temp = _txFinFlags.bits.dupid;
			_txFinFlags.bits.dupid = 0;
			return (temp);
			
		default: return (0);
	}	
}

/*********************************************************************
 * Function:        void _ConnRead(unsigned char hInstance)
 *
 * PreCondition:  	Function _ConnReadRdy() should be executed prior
 *					to calling this function to determine if data has
 *					been received.  
 *
 * Input:       	unsigned char handle to instance		
 *                  
 * Output:      	none	
 *
 * Side Effects:    
 *
 * Overview:        Indicates to the Connection Object that the data 
 *					has been read and the buffer is free to take 
 *					another message.
 *
 * Note:            The function is only executed successfully if
 *					the connection is established.
 ********************************************************************/
void _ConnRead(unsigned char hInstance)
{
	switch (hInstance)
	{
		case 1:	if (_establishFlags.bits.expl) _rxFlag.bits.expl = 0; break;
 
		#if SUPPORT_POLLED || SUPPORT_COS_BOTH_DIR
		case 2:	if (_establishFlags.bits.poll) _rxFlag.bits.poll = 0; break;
		#endif

		#if SUPPORT_BIT_STROBED
		case 3:	if (_establishFlags.bits.strobe) _rxFlag.bits.strobe = 0; break;
		#endif

		#if SUPPORT_COS || SUPPORT_CYCLIC
		case 4: if (_establishFlags.bits.cos) _rxFlag.bits.cos = 0; break;
		#endif

		#if SUPPORT_MULTICAST_POLL
		case 5: if (_establishFlags.bits.multi) _rxFlag.bits.multi = 0; break;
		#endif

		case 6:	_rxFlag.bits.uexpl = 0; break;
		case 7:	_rxFlag.bits.dupid = 0; break;
	}
}	



/*********************************************************************
 * Function:        void _ConnWrite(unsigned char hInstance)
 *
 * PreCondition:	Execute _ConnWriteRdy() to determine if the buffer
 *					is available before executing this function. Also
 *					load the buffer prior to sending.     
 *
 * Input:       	unsigned char handle to instance	
 *                  
 * Output:      	none
 *
 * Side Effects:    
 *
 * Overview:        Indicates to the Connection object instance that 
 * 					all data has been loaded and the connection
 *					is free to transmit. 
 *
 * Note:            The queue bit for the specified connection is set.
 *					
 ********************************************************************/
void _ConnWrite(unsigned char hInstance)	
{
	switch (hInstance)
	{
		case 1:	if (_establishFlags.bits.expl) _txFlag.bits.expl = 1; break;
	    //case 1: _txFlag.bits.expl = 1; break;

		#if SUPPORT_POLLED || SUPPORT_COS_BOTH_DIR
		case 2:	if (_establishFlags.bits.poll) _txFlag.bits.poll = 1; break;
		#endif

		#if SUPPORT_BIT_STROBED
		case 3:	if (_establishFlags.bits.strobe) _txFlag.bits.strobe = 1; break;	
		#endif

		#if SUPPORT_COS || SUPPORT_CYCLIC
		case 4: if (_establishFlags.bits.cos) _txFlag.bits.cos = 1; break;
		#endif

		#if SUPPORT_MULTICAST_POLL
		case 5: if (_establishFlags.bits.multi) _txFlag.bits.multi = 1; break;		
		#endif

		case 6:	_txFlag.bits.uexpl = 1; break;
		case 7:	_txFlag.bits.dupid = 1; break;
	}
}


/*********************************************************************
 * Function:        unsigned char _ConnBusOffErr(void)
 *
 * PreCondition:    
 *
 * Input:       	none	
 *                  
 * Output:      	unsigned char 
 *
 * Side Effects:    
 *
 * Overview:        If a bus-off event has occured then return TRUE
 *
 * Note:            None
 ********************************************************************/
unsigned char _ConnBusOffErr(void)
{
	return(uDNet.BusOffCount == 255);
}





/*********************************************************************
 * Function:        unsigned char _ConnRxManager(void)
 *
 * PreCondition:    CAN (or other I/O) driver must be ready
 *
 * Input:       	none	
 *                  
 * Output:      	unsigned char
 *
 * Side Effects:    
 *
 * Overview:        This function handles any received data events
 *					from the driver and dispaches them to the 
 *					appropriate instance.
 *
 * Note:            This function filters through the identifiers.
 *					Any messages that cannot be processed are ignored.
 *					This function also returns true if an event was
 *					generated in an instance.
 ********************************************************************/
unsigned char _ConnRxManager(void)
{
	// USINT work;
	UINT work;

	//If there is data in the rx buffer then process
	if (CANIsRxRdy())
	{		   
		// Decode the CID (group 2 only, filtering assumed)
		work.word = CANGetRxCID() & 0xE0;

		
		switch(work.bytes.LSB)
		{
			#if SUPPORT_BIT_STROBED
			case 0x00:
				if (!_rxFlag.bits.strobe && _establishFlags.bits.strobe) {_Conn3RxEvent(); return(3);}
				break;
			#endif
			#if SUPPORT_MULTICAST_POLL
			case 0x20:
			 	if (!_rxFlag.bits.multi && _establishFlags.bits.multi) {_Conn5RxEvent(); return(5);}
				break;
			#endif
			#if SUPPORT_COS || SUPPORT_CYCLIC
			case 0x40:
				if (!_rxFlag.bits.cos && _establishFlags.bits.cos) {_Conn4RxEvent(); return(4);} 
				break;
			#endif
			case 0x80:
				if (!_rxFlag.bits.expl && _existentFlags.bits.expl) {_Conn1RxEvent(); return(1);} 
				break;
			#if SUPPORT_POLLED || SUPPORT_COS_BOTH_DIR
			case 0xA0:
				if (!_rxFlag.bits.poll && _establishFlags.bits.poll) {_Conn2RxEvent(); return(2);} 
				break;
			#endif
			case 0xC0:
				if (!_rxFlag.bits.uexpl) _Conn6RxEvent(); return(6);
			case 0xE0:
				if (!_rxFlag.bits.dupid) _Conn7RxEvent(); return(7);	
		}

		CANRead();
		return(0);
	}
	else{return(0);}
}




/*********************************************************************
 * Function:        void _ConnTxOpenManager(void)
 *
 * PreCondition:   	The connection must be open and available.
 *
 * Input:       	none		
 *                  
 * Output:      	none
 *
 * Side Effects:    
 *
 * Overview:        If a message is queued from any connection and
 *					the output buffer is available, then this function
 *					issues an event to the connection instance queued 
 *					to transmit.
 *
 * Note:            The queue is deserialized to eliminate software
 *					imposed priority on the messages.
 ********************************************************************/
void _ConnTxOpenManager(void)
{	
	//If the tx buffer is open and one or more connections are requesting
	//to transmit, then procede to transmit
	if (_txFlag.byte && CANIsTxRdy())
	{
		// Set a new entry point into the loop
		_deSer++;

		// The use of goto in this section is applied to create  
		// multiple entry points into a loop. This has the affect
		// of removing sequencial priority when supporting multiple
		// endpoints on an single serial connection.
		if (_deSer == 1) goto _ConnTxOpenManagerJp1;
		if (_deSer == 2) goto _ConnTxOpenManagerJp2;
		if (_deSer == 3) goto _ConnTxOpenManagerJp3;
		if (_deSer == 4) goto _ConnTxOpenManagerJp4;
		if (_deSer == 5) goto _ConnTxOpenManagerJp5;
		if (_deSer == 6) goto _ConnTxOpenManagerJp6;
		if (_deSer == 7) {_deSer = 0; goto _ConnTxOpenManagerJp7;}
		_deSer = 0;
									  
		while (1)
		{
_ConnTxOpenManagerJp1:
			if (_txFlag.bits.expl)
			{
				if (_establishFlags.bits.expl) _Conn1TxOpenEvent(); 
				else _txFlag.bits.expl = 0;
				return;
			}
			else

_ConnTxOpenManagerJp2:
			#if SUPPORT_POLLED || SUPPORT_COS_BOTH_DIR
			if (_txFlag.bits.poll)
			{
				if (_establishFlags.bits.poll) _Conn2TxOpenEvent(); 
				else _txFlag.bits.poll = 0;
				return;
			}
			else
			#endif

_ConnTxOpenManagerJp3:
			#if SUPPORT_BIT_STROBED
			if (_txFlag.bits.strobe)
			{
				if (_establishFlags.bits.strobe) _Conn3TxOpenEvent(); 
				else _txFlag.bits.strobe = 0;
				return;
			}
			else
			#endif

_ConnTxOpenManagerJp4:
			#if SUPPORT_COS || SUPPORT_CYCLIC
			if (_txFlag.bits.cos)
			{
				if (_establishFlags.bits.cos) _Conn4TxOpenEvent(); 
				else _txFlag.bits.cos = 0;
				return;
			}
			else
			#endif

_ConnTxOpenManagerJp5:
			#if SUPPORT_MULTICAST_POLL
			if (_txFlag.bits.multi)
			{
				if (_establishFlags.bits.multi) _Conn5TxOpenEvent(); 
				else _txFlag.bits.multi = 0;
				return;
			}
			else
			#endif
			
_ConnTxOpenManagerJp6:
			if (_txFlag.bits.uexpl) 
				{_Conn6TxOpenEvent();  return;}
			else

_ConnTxOpenManagerJp7:
			if (_txFlag.bits.dupid) 
				{_Conn7TxOpenEvent(); return;}
		}
	}
}


/*********************************************************************
 * Function:        void _ConnTxManager(void)
 *
 * PreCondition:  	This function assumes the connection instance has
 *					been created (enabled). 	
 *
 * Input:       	none	
 *                  
 * Output:      	none
 *
 * Side Effects:    
 *
 * Overview:        If a message has finished transmitting, then the 
 *					initiator is traced and notified about the 
 *					transmission.
 *
 * Note:            None
 ********************************************************************/
void _ConnTxManager(void)
{
	unsigned char instance;

	instance = CANIsMsgSent();

	// If a message has been transmitted on the bus
	// then who transmitted
	if (instance)
	{
		if (instance == 1) {_Conn1TxEvent();}
		else
		
		#if SUPPORT_POLLED || SUPPORT_COS_BOTH_DIR
		if (instance == 2) {_Conn2TxEvent();}
		else
		#endif

		#if SUPPORT_BIT_STROBED
		if (instance == 3) {_Conn3TxEvent();}
		else
		#endif

		#if SUPPORT_COS || SUPPORT_CYCLIC
		if (instance == 4) {_Conn4TxEvent();}
		else
		#endif

		#if SUPPORT_MULTICAST_POLL
		if (instance == 5) {_Conn5TxEvent();}
		else
		#endif

		if (instance == 6) {_Conn6TxEvent();}
		else
		if (instance == 7) {_Conn7TxEvent();}
	}
}


/*********************************************************************
 * Function:        void _ConnErrorManager(void)
 *
 * PreCondition:    
 *
 * Input:       	none	
 *                  
 * Output:      	none
 *
 * Side Effects:    
 *
 * Overview:        This function captures any bus-off errors from
 *					the driver.
 *
 * Note:            None
 ********************************************************************/
void _ConnErrorManager(void)
{
	//If there is a bus off error then
	if (CANIsBusOffError())
	{
		// Increment the counter up to 255
		if (uDNet.BusOffCount < 255) uDNet.BusOffCount++;
	}
}



/*********************************************************************
 * Function:        void _ConnTimeManager(void)
 *
 * PreCondition:    This function must be called periodically 
 *					according to the specified tick rate.
 *
 * Input:       	none
 *                  
 * Output:      	none
 *
 * Side Effects:    
 *
 * Overview:        Process timer events. 
 *
 * Note:            Each connection manages there own timer.
 ********************************************************************/
void _ConnTimeManager(void)
{
	//Process all timer events
	if (_establishFlags.bits.expl) _Conn1TimerEvent();

	#if SUPPORT_POLLED || SUPPORT_COS_BOTH_DIR
	if (_establishFlags.bits.poll) _Conn2TimerEvent();
	#endif

	#if SUPPORT_BIT_STROBED
	if (_establishFlags.bits.strobe) _Conn3TimerEvent();
	#endif
	
	#if SUPPORT_COS || SUPPORT_CYCLIC
	if (_establishFlags.bits.cos) _Conn4TimerEvent();	
	#endif
	
	#if SUPPORT_MULTICAST_POLL
	if (_establishFlags.bits.multi) _Conn5TimerEvent();	
	#endif
}






/*********************************************************************
 * Function:        void _ConnStateManager(void)
 *
 * PreCondition:    
 *
 * Input:   		none    		
 *                  
 * Output:      	none
 *
 * Side Effects:    
 *
 * Overview:        Synchronize all connection states.
 *
 * Note:            Connection may be deleted.
 ********************************************************************/
void _ConnStateManager(void)
{
	BYTE release;

	if (_existentFlags.bits.expl)
	{
		// Process all stale connections
		switch (uConn1.attrib.state)
		{
			// if conn 1 is deferred and all I/O connections no not exist 
			// or are timed out then delete all connections
			case _STATE_DEFERED_DELETE:
				#if SUPPORT_POLLED || SUPPORT_COS_BOTH_DIR
				if (_establishFlags.bits.poll) break;
				#endif
				#if SUPPORT_BIT_STROBED
				if (_establishFlags.bits.strobe) break;
				#endif
				#if SUPPORT_COS || SUPPORT_CYCLIC
				if (_establishFlags.bits.cos) break;
				#endif
				#if SUPPORT_MULTICAST_POLL
				if (_establishFlags.bits.multi) break;
				#endif
				
													
			// If the explicit messaging connection has transisioned to 
			// to non-exixtent then delete all other connections
			case _STATE_NON_EXISTENT:
				release.byte = uDNet.AllocInfo.AllocChoice.byte;
							
				// Release all allocated connections
				_DNetCloseConnections(release);
				
				// Kill all allocated connections
				uDNet.AllocInfo.AllocChoice.byte = 0;
				uDNet.AllocInfo.MasterMACID = 0xFF;		
		}
	}
}




/*********************************************************************
 * Function:        unsigned char _ConnExplicitEvent()
 *
 * PreCondition:    This function is called from the router.
 *
 * Input:       	none
 *                  
 * Output:      	unsigned char
 *
 * Side Effects:    
 *
 * Overview:        Handle explicit messaging. 
 *
 * Note:            None
 ********************************************************************/
unsigned char _ConnExplMsgHandler(void)
{
	if (mRouteGetInstanceID() == 0)
	{
		switch(mRouteGetServiceID())
	   	{
	   		case SRVS_GET_ATTRIB_SINGLE:
	   			return (_ConnInst0GetAttrib());
	   		default:
	   			mRoutePutError(ERR_SERVICE_NOT_SUPPORTED);
	   			break;
	   	}
	}
	else 

	if ((mRouteGetInstanceID() == 1) && _existentFlags.bits.expl)
		return(_Conn1ExplicitEvent());
	else

	#if SUPPORT_POLLED || SUPPORT_COS_BOTH_DIR
	if ((mRouteGetInstanceID() == 2) && _existentFlags.bits.poll)
		return(_Conn2ExplicitEvent());
	else
	#endif

	#if SUPPORT_BIT_STROBED
	if ((mRouteGetInstanceID() == 3) && _existentFlags.bits.strobe)
		return(_Conn3ExplicitEvent());
	else
	#endif

	#if SUPPORT_COS || SUPPORT_CYCLIC
	if ((mRouteGetInstanceID() == 4) && _existentFlags.bits.cos)
		return(_Conn4ExplicitEvent());
	else
	#endif

	#if SUPPORT_MULTICAST_POLL 
	if ((mRouteGetInstanceID() == 5) && _existentFlags.bits.multi)
		return(_Conn5ExplicitEvent());
	else
	#endif

	{
		mRoutePutError(ERR_OBJECT_DOES_NOT_EXIST);	
	}		
	return (1);
}


/*********************************************************************
 * Function:        unsigned char _ConnInst0GetAttrib(void)
 *
 * PreCondition:    
 *
 * Input:       	none
 *                  
 * Output:      	unsigned char
 *
 * Side Effects:    
 *
 * Overview:        Handle explicit messaging get attribute.
 *
 * Note:            None
 ********************************************************************/
unsigned char _ConnInst0GetAttrib(void)
{	
	switch (mRouteGetAttributeID())
	{
		case _ATTRIB_REVISION:
			mRoutePutByte(_CONN_REVISION & 0xFF);
			mRoutePutByte((_CONN_REVISION & 0xFF00) >> 8);
			break;
				
		default:
			mRoutePutError(ERR_ATTRIB_NOT_SUPPORTED);
			break;
	}
  	return (1);
}



